AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")

function ENT:Initialize()
	self.Entity:SetMaterial( "models/props_combine/tprotato1_sheet" )
	
	self.Entity:PhysicsInit( SOLID_VPHYSICS )
	self.Entity:SetMoveType( MOVETYPE_VPHYSICS )
	self.Entity:SetSolid( SOLID_VPHYSICS )
	
	self.HP = 0
	self.Active = false
	self.ShieldOn = false
	self.RegenAmount = self.MaxHP / math.log10(self.MaxHP) / 40
	
	self.contraption = {}
	
	self.WireDebugName = self.PrintName
	self.Inputs = CDE_Wire_CreateInputs(self.Entity, { "Power" })
	self.Outputs = CDE_Wire_CreateOutputs(self.Entity, { "Integrity" })
	
	CDE_RD_AddResource(self, "energy", 0)
	
	self.Entity:GetPhysicsObject():Wake()
	self.Entity:NextThink(CurTime() + 1)
	
	self.Entity:GetContraption()
 	
	--self.Entity:SetNetworkedInt("EffectCount", 0)
	--self.EffectCount = 0
	
	--self.Entity:SetNetworkedBool("RenderShieldEffect", false)
end

function ENT:DamageShield(damage)
	self.HP = self.HP - damage
	if self.HP <= 0 then
		self.Entity:Deplete()
	end
end

function ENT:Deplete()
	self.HP = 0
	self.ShieldOn = false
	for _,piece in pairs(self.contraption) do
		if piece:IsValid() and piece.CDamage != nil then
			piece.CDamage.isshielded = false
			piece:SetNetworkedBool("IsShielded", false)
		else
			self.Entity:GetContraption()
		end
	end
end

function ENT:OnRemove()
	self.Entity:Deplete()
end

function ENT:Regenerate()
	if CDE_RD_GetResourceAmount(self, "energy") >= (self.EnergyDemand / 4) then
		self.HP = math.Clamp(self.HP + self.RegenAmount, 0, self.MaxHP)
		CDE_RD_ConsumeResource(self, "energy", (self.EnergyDemand / 4))
	else
		self.Entity:Deplete()
	end
end

function ENT:GetContraption()
	self.contraption = CDE_FindContraption( self.Entity )
	--local Vmax, Vmin
	local volume = 0
	for _,Entity in pairs(self.contraption) do
		if (Entity:GetPhysicsObject():IsValid()) then
			volume = volume + Entity:GetPhysicsObject():GetVolume()
		end
--[[ 		if (Vmax == nil) or (Vmin == nil) then
			Vmax = Entity:GetPos()
			Vmin = Entity:GetPos()
		end
		local pos = Entity:GetPos()
		if (pos.x > Vmax.x) then
			Vmax.x = pos.x
		end
		if (pos.x < Vmin.x) then
			Vmin.x = pos.x
		end
		if (pos.y > Vmax.y) then
			Vmax.y = pos.y
		end
		if (pos.y < Vmin.y) then
			Vmin.y = pos.y
		end
		if (pos.z > Vmax.z) then
			Vmax.z = pos.z
		end
		if (pos.z < Vmin.z) then
			Vmin.z = pos.z
		end ]]
	end
	--local size = Vmax - Vmin
	--local volume = size.x * size.y * size.z
	--Msg(size.x .. ", " .. size.y .. ", " .. size.z .. "\n")
	self.EnergyDemand = ((volume*(0.75*math.pi))^(1/3))*self.MaxHP/100000
end

function ENT:PowerOn()
	self.Active = true
	self.Entity:GetContraption()
	-- self.Entity:SetNetworkedBool("RenderShieldEffect", true)
	-- self.EffectCount = 0
	-- self.Entity:SetNetworkedInt("EffectCount", self.EffectCount)
end

function ENT:PowerOff()
	self.Active = false
	self.ShieldOn = false
	-- self.Entity:SetNetworkedBool("RenderShieldEffect", false)
end

function ENT:ProjectShield()
	for _,piece in pairs(self.contraption) do
		timer.Simple(math.Rand(0,2), function(piece) self.Entity:DeployEffect(piece) end, piece)
	end
end

function ENT:DeployEffect(piece)
	piece:SetNetworkedBool("IsShielded", true)
	piece.CDamage.isshielded = true
	piece:SetNetworkedEntity("Shield", self.Entity)
	piece.CDamage.shield = self.Entity
	local efxdata = EffectData()
	efxdata:SetEntity(piece)
	efxdata:SetOrigin(piece:GetPos())
	util.Effect( "shield_hull", efxdata)
	-- self.EffectCount = self.EffectCount + 1
	-- local indexstring = "EffectHull" .. self.EffectCount
	-- self.Entity:SetNetworkedInt("EffectCount", self.EffectCount)
	-- self.Entity:SetNetworkedEntity(indexstring, piece)
end

function ENT:Think()
	local activetext = "Inactive"
	if (self.Active) then
		if (!self.ShieldOn) then
			if self.HP == self.MaxHP then 
			self.Entity:ProjectShield() 
			self.ShieldOn = true
			end	
		end
		self.Entity:Regenerate()
		activetext = "Active"
	end
	local overlaytxt = activetext .. "\nIntegrity: " .. math.Round((self.HP / self.MaxHP)*100) .. "\nDe: " .. self.EnergyDemand
	self.Entity:SetNetworkedString( "GModOverlayText", overlaytxt )
	self.Entity:NextThink(CurTime() + 0.25)
	CDE_Wire_TriggerOutput(self.Entity, "Integrity", math.Round((self.HP / self.MaxHP)*100))
	return true
end

function ENT:Use(p)
	if (p:IsValid() and p:IsPlayer()) then
		self.Entity:GetContraption()
	end
end

function ENT:TriggerInput(k,v)
	if(k=="Power") then
		if(v >= 1) then
			self:PowerOn()
		else
			self:Deplete()
			self:PowerOff()
		end
	end
end

function ShieldHullDuplicate(player, position, angles, maxHP, material, model)
	local newentity = ents.Create("shield_hull_generator")
	newentity:SetPos(position)
	newentity:SetAngles(angles)
	newentity:SetPlayer(player)
	newentity.MaxHP = maxHP
	newentity.DomeMaterial = material
	newentity:SetPlayer(player)
	newentity:SetModel(model)
	newentity:Spawn()
	return newentity
end

function ENT:PreEntityCopy()
	CDE_RD_BuildDupeInfo(self.Entity)
	if not (WireAddon == nil) then
		local DupeInfo = WireLib.BuildDupeInfo(self.Entity)
		if DupeInfo then
			duplicator.StoreEntityModifier( self.Entity, "WireDupeInfo", DupeInfo )
		end
	end
end

function ENT:PostEntityPaste( Player, Ent, CreatedEntities )
	CDE_RD_ApplyDupeInfo(Ent, CreatedEntities)
	if not (WireAddon == nil) and (Ent.EntityMods) and (Ent.EntityMods.WireDupeInfo) then
		WireLib.ApplyDupeInfo(Player, Ent, Ent.EntityMods.WireDupeInfo, function(id) return CreatedEntities[id] end)
	end
end

duplicator.RegisterEntityClass("shield_hull_generator", ShieldHullDuplicate, "pos", "ang", "MaxHP", "DomeMaterial", "Model")